export const TreeUtil = {

  /**
   * 构造树的另一种实现方式
   * @param data
   * @param params
   * @returns {*[]}
   */
  create (data, params = {}) {
    const cData = JSON.parse(JSON.stringify(data))
    const map = {}
    const tData = []
    const attr = {
      id: 'projectCatalog',
      parentId: 'parentProjectCatalog'
    }
    const arg = Object.assign({}, attr, params)
    cData.forEach(item => (map[item[arg.id]] = item))
    cData.forEach(child => {
      child.id = child.projectCatalog
      const mapItem = map[child[arg.parentId]]
      if (mapItem) {
        if (!mapItem.children) {
          mapItem.children = []
        }
        mapItem.children.push(child)
      } else {
        tData.push(child)
      }
    })
    return tData
  },
  /**
   * 构造树型结构数据
   * @param {*} data 数据源
   * @param {*} id id字段 默认 'id'
   * @param {*} parentId 父节点字段 默认 'parentId'
   * @param {*} children 孩子节点字段 默认 'children'
   */
  handleTree (data, id, parentId, children) {
    const config = {
      id: id || 'id',
      parentId: parentId || 'parentId',
      childrenList: children || 'children'
    }

    const childrenMap = {}
    const nodeIds = {}
    const tree = []

    for (const d of data) {
      const parentId = d[config.parentId]
      if (childrenMap[parentId] == null) {
        childrenMap[parentId] = []
      }
      nodeIds[d[config.id]] = d
      childrenMap[parentId].push(d)
    }

    for (const d of data) {
      const parentId = d[config.parentId]
      if (nodeIds[parentId] == null) {
        tree.push(d)
      }
    }

    for (const t of tree) {
      recursionFn(t)
    }

    function recursionFn (o) {
      if (childrenMap[o[config.id]] !== null) {
        o[config.childrenList] = childrenMap[o[config.id]]
      }
      if (o[config.childrenList]) {
        for (const c of o[config.childrenList]) {
          recursionFn(c)
        }
      }
    }
    return tree
  },
  /**
 * 构造树型结构数据
 * @param {*} treeNodes 数据源
 * id 指定数据唯一标识
 * parentId 指定数据对应的 parentId
 */
  handleBigTree (treeNodes, id, parentId) {
    const defaultProps = {
      id: id || 'orgId',
      parentId: parentId || 'parentOrg'
    }
    const nodesMap = new Map(treeNodes.map(node => [node[defaultProps.id], node]))
    const treeRoot = {}

    for (const treeNode of treeNodes) {
      const parent = nodesMap.get(treeNode[defaultProps.parentId]) || treeRoot;

      (parent.children = parent.children ? parent.children : []).push(treeNode)
    }

    // 在这里调用排序函数
    TreeUtil.sortTree(treeRoot, 'orderNum')

    return treeRoot.children || []
  },

  sortTree (node, orderPropName) {
    // 递归函数，用于对每个节点的children进行排序
    if (node.children && node.children.length > 0) {
      node.children.sort((a, b) => {
        // 比较两个节点的orderNumber属性
        return a[orderPropName] - b[orderPropName]
      })

      // 对子节点递归调用排序函数
      for (const child of node.children) {
        TreeUtil.sortTree(child, orderPropName)
      }
    }
  },

  /**
   * 展开/折叠table tree(展开与折叠切换)
   * @param vm vue实例对象
   * @param tableData
   * @param tableRef
   * @param isExpand
   */
  toggleExpand (vm, tableData, tableRef, showExpand) {
    showExpand = showExpand || 'showExpand'
    tableRef = tableRef || 'tableTree'
    vm[showExpand] = !vm[showExpand]
    vm.$nextTick(() => {
      recursionFn(vm, tableData, tableRef, vm[showExpand])
    })

    // 遍历
    function recursionFn (vm, tableData, tableRef, showExpand) {
      tableData.forEach(i => {
        // toggleRowExpansion(i, isExpand)用于多选表格，切换某一行的选中状态，如果使用了第二个参数，则是设置这一行选中与否（selected 为 true 则选中）
        vm.$refs[tableRef].toggleRowExpansion(i, showExpand)
        if (i.children) {
          recursionFn(vm, i.children, tableRef, showExpand)
        }
      })
    }
  },
  /**
   * 设置el-tree节点半选状态
   * @param nodeKeys
   */
  setElTreeHalfCheckedKeys (tree, nodeKeys) {
    for (const nodeKey of nodeKeys) {
      let node = tree.getNode(nodeKey)
      if (!node) {
        return
      }
      do {
        // 应当有状态的父节点在未选中时设置为半选中状态
        if (!node.checked && !node.indeterminate) {
          node.indeterminate = true
        }
        // node.indeterminate = true 仅对一个节点进行半选中状态设置，其父节点不能自动级联设置，则需循环设置级联父节点状态
        node = node.parent
      } while (node)
    }
  }
}
